package com.xyht.sca_s.student_manage_system.modules.fileManagement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.fileManagement.entity.SmsFileManagement;
import com.xyht.sca_s.student_manage_system.modules.fileManagement.entity.req.SmsFileManagementReq;
import com.xyht.sca_s.student_manage_system.modules.fileManagement.entity.resp.SmsFileManagementReap;
import com.xyht.sca_s.student_manage_system.modules.fileManagement.mapper.SmsFileManagementMapper;
import com.xyht.sca_s.student_manage_system.modules.fileManagement.service.SmsFileManagementService;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.fileManagement.constant.CommonConstant.FILE_UPLOAD_MAX;
import static com.xyht.sca_s.student_manage_system.modules.fileManagement.constant.FilePathConstant.FILE_MANAGEMENT_PATH;
import static com.xyht.sca_s.student_manage_system.modules.fileManagement.constant.FilePathConstant.FILE_MANAGEMENT_PATH_LINUX;
import static com.xyht.sca_s.student_manage_system.modules.fileManagement.constant.FileTypeConstant.FILE_TYPE_FILE;
import static com.xyht.sca_s.student_manage_system.modules.fileManagement.constant.FileTypeConstant.FILE_TYPE_FOLDER;

/**
 * <p>
 * 文件管理 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-02-14
 */
@Service
public class SmsFileManagementServiceImpl extends ServiceImpl<SmsFileManagementMapper, SmsFileManagement> implements SmsFileManagementService {
    @Autowired
    private SmsFileManagementMapper smsFileManagementMapper;
    @Autowired
    private SmsUserMapper smsUserMapper;


    @Override
    @Transactional
    public ResponseResult addFileManagement(Integer type, String name, String description,
                                            String p_id, String file_pic, String user_id, MultipartFile file) {
        if (isNullOrEmpty(type) || isNullOrEmpty(p_id) || isNullOrEmpty(name)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if (type == FILE_TYPE_FILE) {
            if (isNullOrEmpty(file)) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        }

        SmsUser smsUser = smsUserMapper.selectById(user_id);
        String user_name = smsUser.getRealName();

        SmsFileManagement fileManagement = new SmsFileManagement();
        if (type == FILE_TYPE_FOLDER) {
            fileManagement.setFileName(name);
            fileManagement.setDescription(description);
            fileManagement.setPId(p_id);
            fileManagement.setType(FILE_TYPE_FOLDER);
            fileManagement.setUploadUserId(user_id);
            fileManagement.setUploadUserName(user_name);
            smsFileManagementMapper.insert(fileManagement);
        } else {
            if (file.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            String OSName = System.getProperty("os.name");
            String filePath = OSName.toLowerCase().startsWith("win") ? FILE_MANAGEMENT_PATH
                    : FILE_MANAGEMENT_PATH_LINUX;

            String fileName = file.getOriginalFilename();

            int size = Math.round(file.getSize() / 1024);
            int sizeMB = Math.round(size / 1024);
            if (sizeMB > FILE_UPLOAD_MAX) {
                return CommonResult.failed(CommonCodeEnum.FILE_SIZE_LIMIT_EXCEEDED);
            }
            log.debug(fileName + "-->" + size + "KB");
            String[] fileTypeArr = fileName.split("\\.");
            String fileType = fileTypeArr[fileTypeArr.length - 1];

            String timeTemp = new Date().getTime() + "";
            String completePath = filePath + timeTemp + "." + fileType;
            String newFileName = timeTemp + "." + fileType;
            File dest = new File(completePath);
            if (!dest.getParentFile().exists()) { //判断文件父目录是否存在
                dest.getParentFile().mkdir();
            }
            try {
                file.transferTo(dest); //保存文件
                Map<String, Object> map = new HashMap<>();
                map.put("oldFileName", fileName);
                map.put("newFileName", newFileName);

                fileManagement.setType(FILE_TYPE_FILE);
                fileManagement.setPId(p_id);
                fileManagement.setFilePath(newFileName);
                fileManagement.setFileName(name);
                fileManagement.setFilePic(file_pic);
                fileManagement.setFileSize(size);
                fileManagement.setUploadUserId(user_id);
                fileManagement.setUploadUserName(user_name);
                fileManagement.setDescription(description);
                fileManagement.setSuffix(fileType);
                smsFileManagementMapper.insert(fileManagement);
            } catch (MaxUploadSizeExceededException e) {
                // TODO Auto-generated catch block
                return CommonResult.failed(CommonCodeEnum.FILE_SIZE_LIMIT_EXCEEDED);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return CommonResult.failed(CommonCodeEnum.FAIL);
            }
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult downloadFileManagement(String id, String path, HttpServletResponse response) {
        if (isNullOrEmpty(path) || isNullOrEmpty(id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsFileManagement smsFileManagement = smsFileManagementMapper.selectById(id);
        if (smsFileManagement == null || smsFileManagement.getId() == null) {
            return CommonResult.failed(CommonCodeEnum.FILE_MANAGEMENT_NOT_EXIST);
        }

        String fileName = "";
        FileInputStream fis = null; //文件输入流
        BufferedInputStream bis = null;
        OutputStream os; //输出流

        String OSName = System.getProperty("os.name");
        String filePath = OSName.toLowerCase().startsWith("win") ? FILE_MANAGEMENT_PATH
                : FILE_MANAGEMENT_PATH_LINUX;
        String completePath = filePath + path;

        File file = new File(completePath);
        if (file.getParentFile().exists()) { //判断文件父目录是否存在
            try {

                response.setContentType("application/force-download");
//                response.setContentType("image/**");
                response.setCharacterEncoding("UTF-8");
                // response.setContentType("application/force-download");
//                response.setHeader("Content-Disposition", "attachment;fileName=" + java.net.URLEncoder.encode("123123.jpg", "UTF-8"));
                String fileRealName = smsFileManagement.getFileName() +
                        "." +
                        smsFileManagement.getSuffix();
                response.setHeader("file-name", fileRealName);
                response.setHeader("file-type", "download");
                response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
                response.setHeader("Content-Disposition", "inline");
                byte[] buffer = new byte[1024];

                os = response.getOutputStream();
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);

                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer);
                    i = bis.read(buffer);
                }
            } catch (FileNotFoundException e) {
                return CommonResult.failed(CommonCodeEnum.DATA_NOT_FOUND);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return CommonResult.failed(CommonCodeEnum.FAIL);
            }
            log.debug("----------file download---" + fileName);
            try {
                os.flush();
                os.close();

                bis.close();
                fis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return CommonResult.failed(CommonCodeEnum.FAIL);
            }
            return null;
        } else {
            return CommonResult.failed(CommonCodeEnum.DATA_NOT_FOUND);
        }
    }

    @Override
    public ResponseResult getFileManagementList(String id, String searchStr, Integer pageNum, Integer pageSize) {
        Page<SmsFileManagement> page = new Page<>(pageNum, pageSize);
        QueryWrapper<SmsFileManagement> queryWrapper = new QueryWrapper<>();
        if (!isNullOrEmpty(id)) {
            queryWrapper
                    .lambda()
                    .eq(SmsFileManagement::getPId, id);
        }
        if (!isNullOrEmpty(searchStr)) {
            queryWrapper
                    .lambda()
                    .like(SmsFileManagement::getFileName, searchStr);
        }
        queryWrapper
                .lambda()
                .orderByAsc(SmsFileManagement::getType)
                .orderByDesc(SmsFileManagement::getCreateTime);
        smsFileManagementMapper.selectPage(page, queryWrapper);

        List<SmsFileManagement> smsFileManagementList = page.getRecords();
        int total = (int) page.getTotal();
        List<SmsFileManagementReap> reapList = smsFileManagementList.stream().map(file -> {
            SmsFileManagementReap fileManagementReap = new SmsFileManagementReap();
            BeanUtils.copyProperties(file, fileManagementReap);
            return fileManagementReap;
        }).collect(Collectors.toList());
        return CommonResult.success(reapList,total);
    }

    @Override
    public ResponseResult updateFileManagement(SmsFileManagementReq smsFileManagementReq) {
        if (isNullOrEmpty(smsFileManagementReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsFileManagement smsFileManagement = smsFileManagementMapper.selectById(smsFileManagementReq.getId());
        if (smsFileManagement == null || smsFileManagement.getId() == null) {
            return CommonResult.failed(CommonCodeEnum.FILE_MANAGEMENT_NOT_EXIST);
        }
        if (!isNullOrEmpty(smsFileManagementReq.getPId())) {
            SmsFileManagement targetFile = smsFileManagementMapper.selectById(smsFileManagementReq.getPId());
            if (targetFile == null || targetFile.getId() == null) {
                return CommonResult.failed(CommonCodeEnum.FILE_MANAGEMENT_MOVE_NOT_EXIST);
            }
            if (targetFile.getType() == FILE_TYPE_FILE) {
                return CommonResult.failed(CommonCodeEnum.FILE_MANAGEMENT_MOVE_ERR);
            }
        }

        SmsFileManagement updateFileManagement = new SmsFileManagement();
        updateFileManagement.setId(smsFileManagementReq.getId());
        if (!isNullOrEmpty(smsFileManagementReq.getFileName())) {
            updateFileManagement.setFileName(smsFileManagementReq.getFileName());
        }
        if (!isNullOrEmpty(smsFileManagementReq.getPId())) {
            updateFileManagement.setPId(smsFileManagementReq.getPId());
        }
        if (!isNullOrEmpty(smsFileManagementReq.getDescription())) {
            updateFileManagement.setDescription(smsFileManagementReq.getDescription());
        }
        if (!isNullOrEmpty(smsFileManagementReq.getFilePic())) {
            updateFileManagement.setFilePic(smsFileManagementReq.getFilePic());
        }
        smsFileManagementMapper.updateById(updateFileManagement);
        return CommonResult.success();
    }

    @Override
    public ResponseResult deleteFileManagement(SmsFileManagementReq smsFileManagementReq) {
        if (isNullOrEmpty(smsFileManagementReq.getId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsFileManagement smsFileManagement = smsFileManagementMapper.selectById(smsFileManagementReq.getId());
        if (smsFileManagement == null || smsFileManagement.getId() == null) {
            return CommonResult.failed(CommonCodeEnum.FILE_MANAGEMENT_NOT_EXIST);
        }

        if (smsFileManagement.getType() == FILE_TYPE_FOLDER) {
            List<SmsFileManagement> childFileList = smsFileManagementMapper.selectList(new QueryWrapper<SmsFileManagement>()
                    .lambda()
                    .eq(SmsFileManagement::getPId, smsFileManagementReq.getId()));
            if (childFileList != null && childFileList.size() > 0){
                return CommonResult.failed(CommonCodeEnum.FILE_MANAGEMENT_DELETE_HAVE_CHILD_FILE);
            }
        }

        smsFileManagementMapper.deleteById(smsFileManagementReq.getId());
        return CommonResult.success();
    }
}
